package eco2automotive.util;

import eco2automotive.data.ErrorCode;
import eco2automotive.data.HashErrorCode;
import eco2automotive.data.Protocol;
import eco2automotive.data.Parameter;
import eco2automotive.data.HashParameters;
import eco2automotive.data.ValuePID;
import eco2automotive.data.OperationMode;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**  
 *  Imports specific data from the xml files: </br>
 * eco2automotive/data/*.xml
  * @version 1.0
  * @autor Fco. Javier Sánchez Esparza
  */ 
public class ImportXMLdata {
    Document dom;
    List listOfConnections;
    HashErrorCode hash;
    HashParameters hash2;
    ArrayList arrElement;
    Protocol protocol;
    OperationMode op;
    
    /**
     * 
     */
    public ImportXMLdata() {
        listOfConnections = new ArrayList();
        hash=new HashErrorCode();
        hash2=new HashParameters();
        arrElement=new ArrayList();
        
        //imprimirResultados();
    }
    //
    /**
     * Parser a xml file 
     * @param dir
     */
    public void parseXml(String dir) {
        // 1. Get the DocumentBuilderFactory object
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            // 2.Use the DocumentBuilderFactory, does a DocumentBuilder document
            DocumentBuilder db = dbf.newDocumentBuilder();
            // 3. Parser te new document
            dom = db.parse(dir);
        } catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (SAXException se) {
            se.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }           
    //Return a integer value from a label named
    private int getInteger(Element elemento, String nombreEtiqueta) {
        return Integer.parseInt(getText(elemento, nombreEtiqueta));
    }
   //Return a "Element" value from a label named
    private String getText(Element elemento, String nombreEtiqueta) {
        String texto = null;
        NodeList nl = elemento.getElementsByTagName(nombreEtiqueta);
        if (nl != null && nl.getLength() > 0) {
            Element el = (Element) nl.item(0);
            texto = el.getFirstChild().getNodeValue();
        }
        return texto;
    }        
    /**
     * Utility: Print results
     */
    public void printResult() {
         Iterator it = listOfConnections.iterator();
         while (it.hasNext())
             System.out.println(it.next().toString());
     }    
 //==========================================================================
     /**
      * Get the HashErrorCode HashMap
      * @return
      */
     public HashErrorCode parseTroubleCodes() {
        // 1. Obtener el documento raiz
        Element docEle = dom.getDocumentElement();
        // 2. Obtener un nodelist de elementos <conexion>
        NodeList nl = docEle.getElementsByTagName("error");
        if (nl != null && nl.getLength() > 0) {
            for (int i = 0; i < nl.getLength(); i++) {
                // a. Obtener el elemento
                Element elemento = (Element) nl.item(i);
                // b. Obtener el objeto empleado
                ErrorCode conexion = getErrorCodeElement(elemento);
                //obtener elemento ErrorCode
                // c. Aniadirlo a la lista
               hash.insertError(conexion);
               //---- listOfConnections.add(conexion);
            }
        }
        return hash;
    }       
    /**
     * 
     * @param elemento
     * @return
     */
    public ErrorCode getErrorCodeElement(Element elemento) {
        String code = getText(elemento, "code");
	String desc = getText(elemento, "description");     
	// Crear un objeto ArchivoConfiguracion con los datos recibidos
        ErrorCode d = new ErrorCode(code, desc);
        System.out.println("Obetniendo datos XML >>"+d.getCode()+">>"+
                d.getDescription());
        return d;
    }
//==============================================================================
    /**
     * Get a protocol object
     * @param elemento
     * @return
     */
    public Protocol getProtocolElement(Element elemento) {
        String code = getText(elemento, "id");
	String desc = getText(elemento, "description");  
	//Revisar esto.... code.charAt(0)
        Protocol p = new Protocol(code.charAt(0), desc);
        //
        System.out.println("Getting data XML >>"+p.getId()+">>"+
                p.getDescription());
        return p;
    }
/**
 * Get a Arraylist object of Protocols
 * @return
 */
public ArrayList parseTableOfProtocols(){
       
        Element docEle = dom.getDocumentElement();
        NodeList nl = docEle.getElementsByTagName("protocol");
        if (nl != null && nl.getLength() > 0) {
            for (int i = 0; i < nl.getLength(); i++) {
                Element elemento = (Element) nl.item(i);                
                Protocol conexion = getProtocolElement(elemento);                
               this.arrElement.add(conexion);
            }
        }
       return arrElement;
}
//==============================================================================
/**
 * Get a Parameter object
 * @param elemento
 * @return
 */
public Parameter getParameterElement(Element elemento) {
    /*
     <param>	
     * <mode>	01	</mode>	
     * <id>	00	</id>	
     * <bytes>	4	</bytes>	
     * <description>	PIDs supported [01 - 20]	</description>	
     * <min>	0	</min>	
     * <max>	0	</max>	
     * <units>	-	</units>	
     * <formula>	[*]	</formula>	
     </param>
     */
    
    ValuePID pid_value;
        String mode =getText(elemento, "mode");
	String pid = getText(elemento, "pid");
        
        int bytesreturned=0;
        String bytes=getText(elemento,"bytes");
        
        String description = getText(elemento, "description");
        String formula=getText(elemento, "formula");
        mode=mode.replaceAll(" ","");
        mode=mode.replaceAll("\\t","");

        pid=pid.replaceAll(" ","");
        pid=pid.replaceAll("\\t","");
        
        bytes=bytes.replaceAll(" ","");
        bytes=bytes.replaceAll("\\t","");
        description=description.trim();
        
        /**/
        String min =getText(elemento, "min");
        double mn;
	String max = getText(elemento, "max");
        double mx;
        String units =getText(elemento, "units");
        String masc =getText(elemento, "masc");      
        boolean encoded=false; 
                 
        formula=formula.replaceAll("\\t","");
        formula=formula.trim();       

        //Contains a sting="[*]" special treatement
        if (formula.isEmpty())
        { 
            encoded=false;
        }
        else
        {
             if(formula.contentEquals("[*]"))
                encoded=true;
             else
                 encoded=false;
        }        
                        
        try{bytesreturned = Integer.parseInt(bytes);}catch(Exception e){bytesreturned=0;}            
        try{ mn=Double.parseDouble(min);}catch(Exception e){mn=0.0;}
        try{mx=Double.parseDouble(max);}catch(Exception e){  mx=0.0;}
       
        ValuePID p= new ValuePID(mn,mx,formula,masc,units,encoded);

System.out.println("Xml datos <mode> :"+mode+" <pid> :"+pid +" <description> :"+description+" <bytes> :"
                +bytesreturned+" <encoded>: "+encoded);                     

        Parameter pr=new Parameter(mode,pid,bytesreturned,description);        
         pr.addPID(p);
        return pr;
    }
/**
 * Get a HashMap of Parameter object
 * @return
 */
public HashParameters parseTableOfParameter(){
        Element docEle = dom.getDocumentElement();
        NodeList nl = docEle.getElementsByTagName("param");
        if (nl != null && nl.getLength() > 0) {
            for (int i = 0; i < nl.getLength(); i++) {
                Element elemento = (Element) nl.item(i);
                Parameter p =getParameterElement(elemento);
                hash2.insertParameter(p);         
            }
        }
        return hash2;
    }
//==============================================================================
/**
 * Get a OperationMode object
 * @param elemento
 * @return
 */
public OperationMode getOperationModeElement(Element elemento) {
        String code = getText(elemento, "id");
	String desc = getText(elemento, "description");  
	//Revisar esto.... code.charAt(0)
        OperationMode p = new OperationMode(code, desc);
        //
        System.out.println("Obetniendo datos XML >>"+p.getId()+">>"+
                p.getDescription());
        return p;
    }
/**
 * Return a ArrayList of Operations Modes
 * @return
 */
public ArrayList parseOperationModeElement(){
       
        Element docEle = dom.getDocumentElement();
        NodeList nl = docEle.getElementsByTagName("Mode");
        if (nl != null && nl.getLength() > 0) {
            for (int i = 0; i < nl.getLength(); i++) {
                Element elemento = (Element) nl.item(i);                
                Protocol conexion = getProtocolElement(elemento);                
               this.arrElement.add(conexion);
            }
        }
       return arrElement;
}


}